<template>
  <div class="sales-trend-chart">
    <div class="chart-header">
      <div class="title-section">
        <h3 class="chart-title">销售趋势分析</h3>
        <p class="chart-subtitle">{{ getCurrentPeriodDesc() }}</p>
      </div>
      <div class="time-selector">
        <el-radio-group v-model="selectedTimeUnit" @change="handleTimeUnitChange" size="small">
          <el-radio-button label="day">日</el-radio-button>
          <el-radio-button label="week">周</el-radio-button>
          <el-radio-button label="month">月</el-radio-button>
        </el-radio-group>
      </div>
    </div>

    <div class="chart-overview">
      <div class="overview-item">
        <div class="overview-label">日均销售额</div>
        <div class="overview-value">{{ formatCurrency(averageSales) }}</div>
      </div>
      <div class="overview-divider"></div>
      <div class="overview-item">
        <div class="overview-label">平均利润率</div>
        <div class="overview-value profit-value">{{ profitRate }}%</div>
      </div>
      <div class="overview-divider"></div>
      <div class="overview-item">
        <div class="overview-label">销售峰值日期</div>
        <div class="overview-value">{{ peakSalesDate }}</div>
      </div>
    </div>

    <div class="chart-container" ref="chartRef">
      <div class="loading-overlay" v-if="loading">
        <el-icon class="is-loading"><Loading /></el-icon>
        <span>加载中...</span>
      </div>
    </div>

    <div class="chart-footer">
      <div class="period-info">
        <div class="period-label">统计周期</div>
        <div class="period-value">{{ periodRangeText }}</div>
      </div>
      <div class="totals-info">
        <div class="total-item">
          <span class="total-label">总销售额：</span>
          <span class="total-value">{{ formatCurrency(totalSales) }}</span>
        </div>
        <div class="total-item">
          <span class="total-label">总利润：</span>
          <span class="total-value profit-value">{{ formatCurrency(totalProfit) }}</span>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, onMounted, onUnmounted, watch, computed, PropType, nextTick } from 'vue'
import * as echarts from 'echarts/core'
import { LineChart, BarChart } from 'echarts/charts'
import {
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent,
  DataZoomComponent,
  MarkPointComponent,
  MarkLineComponent
} from 'echarts/components'
import { CanvasRenderer } from 'echarts/renderers'
import { Loading } from '@element-plus/icons-vue'

echarts.use([
  TitleComponent,
  TooltipComponent,
  GridComponent,
  LegendComponent,
  LineChart,
  BarChart,
  DataZoomComponent,
  MarkPointComponent,
  MarkLineComponent,
  CanvasRenderer
])

interface ChartDataItem {
  date: string
  sales: number
  profit: number
}

export default defineComponent({
  name: 'SalesTrendChart',
  components: {
    Loading
  },
  props: {
    chartData: {
      type: Array as PropType<ChartDataItem[]>,
      required: true
    },
    loading: {
      type: Boolean,
      default: false
    }
  },
  emits: ['time-unit-change'],
  setup(props, { emit }) {
    const chartRef = ref<HTMLElement | null>(null)
    const selectedTimeUnit = ref('day')
    let chart: echarts.ECharts | null = null
    
    // 格式化货币
    const formatCurrency = (value: number) => {
      if (value >= 1000000) {
        return (value / 1000000).toFixed(2) + '百万'
      } else if (value >= 10000) {
        return (value / 10000).toFixed(2) + '万'
      }
      
      return new Intl.NumberFormat('zh-CN', {
        minimumFractionDigits: 0,
        maximumFractionDigits: 0
      }).format(value)
    }
    
    // 计算总销售额
    const totalSales = computed(() => {
      if (!Array.isArray(props.chartData)) return 0
      return props.chartData.reduce((sum, item) => sum + item.sales, 0)
    })
    
    // 计算总利润
    const totalProfit = computed(() => {
      if (!Array.isArray(props.chartData)) return 0
      return props.chartData.reduce((sum, item) => sum + item.profit, 0)
    })
    
    // 计算日均销售额
    const averageSales = computed(() => {
      if (!Array.isArray(props.chartData) || props.chartData.length === 0) return 0
      return totalSales.value / props.chartData.length
    })
    
    // 计算利润率
    const profitRate = computed(() => {
      if (totalSales.value === 0) return 0
      return Math.round((totalProfit.value / totalSales.value) * 100)
    })
    
    // 获取销售峰值日期
    const peakSalesDate = computed(() => {
      if (!Array.isArray(props.chartData) || props.chartData.length === 0) return '无数据'
      
      const maxSalesItem = props.chartData.reduce((max, item) => 
        item.sales > max.sales ? item : max, props.chartData[0])
      
      // 格式化日期，例如从 "2023-01-01" 转换为 "01-01"
      const dateParts = maxSalesItem.date.split('-')
      return dateParts.length > 2 ? `${dateParts[1]}-${dateParts[2]}` : maxSalesItem.date
    })
    
    // 统计期间范围文本
    const periodRangeText = computed(() => {
      if (!Array.isArray(props.chartData) || props.chartData.length === 0) return '无数据'
      
      const startDate = props.chartData[0].date
      const endDate = props.chartData[props.chartData.length - 1].date
      
      return `${startDate} 至 ${endDate}`
    })
    
    // 获取当前周期描述
    const getCurrentPeriodDesc = () => {
      const periodMap = {
        day: '每日销售趋势',
        week: '每周销售趋势',
        month: '每月销售趋势'
      }
      
      return periodMap[selectedTimeUnit.value as keyof typeof periodMap] || '销售趋势'
    }
    
    // 初始化图表
    const initChart = () => {
      if (!chartRef.value) return
      
      chart = echarts.init(chartRef.value)
      updateChart()
      
      window.addEventListener('resize', handleResize)
    }
    
    // 更新图表数据
    const updateChart = () => {
      if (!chart || !chartRef.value) return
      
      // 检查chartData是否为数组
      if (!Array.isArray(props.chartData) || props.chartData.length === 0) {
        // 如果不是数组或为空数组，设置空数据
        const option = {
          xAxis: {
            type: 'category',
            data: []
          },
          yAxis: [
            {
              type: 'value',
              name: '销售额',
              axisLabel: {
                formatter: (value: number) => formatCurrency(value),
                color: '#606266'
              }
            },
            {
              type: 'value',
              name: '利润',
              axisLabel: {
                formatter: (value: number) => formatCurrency(value),
                color: '#606266'
              }
            }
          ],
          series: [
            {
              name: '销售额',
              type: 'line',
              data: []
            },
            {
              name: '利润',
              type: 'bar',
              yAxisIndex: 1,
              data: []
            }
          ]
        }
        try {
          chart.setOption(option)
        } catch (e) {
          console.error('更新空图表数据失败:', e)
        }
        return
      }
      
      try {
        const xAxisData = props.chartData.map(item => item.date)
        const salesData = props.chartData.map(item => item.sales)
        const profitData = props.chartData.map(item => item.profit)
        
        // 找出最大销售额和最小销售额的索引
        const maxSalesIndex = salesData.indexOf(Math.max(...salesData))
        const minSalesIndex = salesData.indexOf(Math.min(...salesData))
        
        // 计算平均线的值
        const avgSales = salesData.reduce((sum, val) => sum + val, 0) / salesData.length
        
        const option = {
          tooltip: {
            trigger: 'axis',
            axisPointer: {
              type: 'cross',
              label: {
                backgroundColor: '#6a7985'
              }
            },
            formatter: function(params: any) {
              const date = params[0].axisValue
              let salesValue = 0
              let profitValue = 0
              
              params.forEach((param: any) => {
                if (param.seriesName === '销售额') {
                  salesValue = param.value
                }
                if (param.seriesName === '利润') {
                  profitValue = param.value
                }
              })
              
              // 计算利润率
              const profitRate = salesValue ? Math.round((profitValue / salesValue) * 100) : 0
              
              return `
                <div style="font-weight:bold;margin-bottom:5px">${date}</div>
                <div style="margin:3px 0">
                  <span style="display:inline-block;width:10px;height:10px;border-radius:50%;background-color:#409EFF;margin-right:5px"></span>
                  销售额：${formatCurrency(salesValue)}
                </div>
                <div style="margin:3px 0">
                  <span style="display:inline-block;width:10px;height:10px;border-radius:50%;background-color:#67C23A;margin-right:5px"></span>
                  利润：${formatCurrency(profitValue)}
                </div>
                <div style="margin:3px 0">
                  <span style="display:inline-block;width:10px;height:10px;border-radius:50%;background-color:#F56C6C;margin-right:5px"></span>
                  利润率：${profitRate}%
                </div>
              `
            }
          },
          legend: {
            data: ['销售额', '利润'],
            right: 10,
            top: 0
          },
          grid: {
            left: '3%',
            right: '4%',
            bottom: '15%',
            top: '15%',
            containLabel: true
          },
          xAxis: {
            type: 'category',
            boundaryGap: false,
            data: xAxisData,
            axisLine: {
              lineStyle: {
                color: '#dcdfe6'
              }
            },
            axisLabel: {
              color: '#606266'
            }
          },
          yAxis: [
            {
              type: 'value',
              name: '销售额',
              axisLabel: {
                formatter: (value: number) => formatCurrency(value),
                color: '#606266'
              },
              splitLine: {
                lineStyle: {
                  type: 'dashed',
                  color: '#ebeef5'
                }
              }
            },
            {
              type: 'value',
              name: '利润',
              axisLabel: {
                formatter: (value: number) => formatCurrency(value),
                color: '#606266'
              },
              splitLine: {
                show: false
              }
            }
          ],
          dataZoom: [
            {
              type: 'inside',
              start: 0,
              end: 100
            },
            {
              start: 0,
              end: 100
            }
          ],
          series: [
            {
              name: '销售额',
              type: 'line',
              data: salesData,
              smooth: true,
              symbol: 'emptyCircle',
              symbolSize: 6,
              showSymbol: false,
              itemStyle: {
                color: '#409EFF'
              },
              lineStyle: {
                width: 3,
                shadowColor: 'rgba(64, 158, 255, 0.3)',
                shadowBlur: 10,
                shadowOffsetY: 5
              },
              areaStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  {
                    offset: 0,
                    color: 'rgba(64, 158, 255, 0.3)'
                  },
                  {
                    offset: 1,
                    color: 'rgba(64, 158, 255, 0.05)'
                  }
                ])
              },
              markPoint: {
                data: [
                  { type: 'max', name: '最大值', symbolSize: 65 },
                  { type: 'min', name: '最小值', symbolSize: 65 }
                ],
                label: {
                  formatter: (params: any) => formatCurrency(params.value)
                }
              },
              markLine: {
                data: [
                  {
                    type: 'average',
                    name: '平均值',
                    label: {
                      formatter: '平均: {c}'
                    }
                  }
                ],
                lineStyle: {
                  color: '#E6A23C',
                  type: 'dashed'
                },
                label: {
                  formatter: (params: any) => '平均: ' + formatCurrency(params.value)
                }
              }
            },
            {
              name: '利润',
              type: 'bar',
              yAxisIndex: 1,
              data: profitData,
              itemStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  { offset: 0, color: '#67C23A' },
                  { offset: 1, color: '#95d475' }
                ]),
                borderRadius: [3, 3, 0, 0]
              },
              barWidth: '40%',
              barGap: '-70%',
              z: 1
            }
          ]
        }
        
        chart.setOption(option)
      } catch (e) {
        console.error('更新图表数据失败:', e)
      }
    }
    
    // 处理时间单位变更
    const handleTimeUnitChange = (unit: string | number | boolean | undefined) => {
      if (typeof unit === 'string') {
        emit('time-unit-change', unit)
      }
    }
    
    // 响应式调整图表大小
    const handleResize = () => {
      if (chart && chartRef.value) {
        try {
          chart.resize()
        } catch (e) {
          console.error('调整图表大小失败:', e)
        }
      }
    }
    
    // 监听数据变化，更新图表
    watch(
      () => props.chartData,
      () => {
        if (chart && chartRef.value) {
          nextTick(updateChart)
        }
      },
      { deep: true }
    )
    
    // 监听加载状态变化
    watch(
      () => props.loading,
      (newVal) => {
        if (!newVal && chart && chartRef.value) {
          nextTick(updateChart)
        }
      }
    )
    
    // 组件挂载时初始化图表
    onMounted(() => {
      // 使用nextTick确保DOM已渲染完成
      nextTick(() => {
        try {
          if (chartRef.value) {
            initChart()
          }
        } catch (e) {
          console.error('挂载时初始化图表失败:', e)
        }
      })
    })
    
    // 组件卸载时销毁图表实例
    onUnmounted(() => {
      // 先移除事件监听器，避免内存泄漏
      window.removeEventListener('resize', handleResize)
      
      // 然后销毁图表实例
      if (chart) {
        try {
          chart.dispose()
        } catch (e) {
          console.error('卸载组件时销毁图表失败:', e)
        }
        chart = null
      }
    })
    
    return {
      chartRef,
      selectedTimeUnit,
      formatCurrency,
      handleTimeUnitChange,
      totalSales,
      totalProfit,
      averageSales,
      profitRate,
      peakSalesDate,
      periodRangeText,
      getCurrentPeriodDesc
    }
  }
})
</script>

<style scoped lang="scss">
.sales-trend-chart {
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
  padding: 20px;
  height: 100%;
  display: flex;
  flex-direction: column;
  
  .chart-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin-bottom: 15px;
    
    .title-section {
      .chart-title {
        margin: 0 0 4px 0;
        font-size: 16px;
        font-weight: 600;
        color: #303133;
      }
      
      .chart-subtitle {
        margin: 0;
        font-size: 12px;
        color: #909399;
      }
    }
  }
  
  .chart-overview {
    display: flex;
    background-color: #f8f9fa;
    border-radius: 8px;
    padding: 12px 16px;
    margin-bottom: 20px;
    
    .overview-item {
      flex: 1;
      text-align: center;
      
      .overview-label {
        font-size: 12px;
        color: #909399;
        margin-bottom: 5px;
      }
      
      .overview-value {
        font-size: 16px;
        font-weight: 600;
        color: #303133;
        
        &.profit-value {
          color: #67C23A;
        }
      }
    }
    
    .overview-divider {
      width: 1px;
      background-color: #dcdfe6;
      margin: 0 15px;
    }
  }
  
  .chart-container {
    flex: 1;
    position: relative;
    min-height: 300px;
    
    .loading-overlay {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-color: rgba(255, 255, 255, 0.7);
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      z-index: 1;
      
      .is-loading {
        font-size: 24px;
        color: #409EFF;
        margin-bottom: 10px;
      }
      
      span {
        font-size: 14px;
        color: #606266;
      }
    }
  }
  
  .chart-footer {
    margin-top: 15px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 12px;
    
    .period-info {
      display: flex;
      align-items: center;
      
      .period-label {
        color: #909399;
        margin-right: 5px;
      }
      
      .period-value {
        color: #606266;
        font-weight: 500;
      }
    }
    
    .totals-info {
      display: flex;
      gap: 15px;
      
      .total-item {
        .total-label {
          color: #909399;
        }
        
        .total-value {
          font-weight: 600;
          color: #303133;
          
          &.profit-value {
            color: #67C23A;
          }
        }
      }
    }
  }
}
</style> 